package com.feityz.system.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bstek.uflo.model.HistoryProcessInstance;
import com.bstek.uflo.model.ProcessDefinition;
import com.bstek.uflo.model.ProcessInstance;
import com.bstek.uflo.model.task.Task;
import com.bstek.uflo.model.task.TaskState;
import com.bstek.uflo.process.node.Node;
import com.bstek.uflo.process.node.StartNode;
import com.bstek.uflo.process.node.TaskNode;
import com.bstek.uflo.process.node.UserData;
import com.bstek.uflo.service.HistoryService;
import com.bstek.uflo.service.ProcessService;
import com.bstek.uflo.service.TaskOpinion;
import com.bstek.uflo.service.TaskService;
import com.feityz.system.dao.ProcessIncetanceMapper;
import com.feityz.system.entity.ProcessIncetanceVo;
import com.feityz.system.entity.User;
import com.feityz.system.input.ProcessIncetanceHisInput;
import com.feityz.system.input.ProcessIncetanceInput;
import com.feityz.system.service.IProcessIncetanceService;
import com.feityz.system.service.IUserService;
import com.feityz.system.vo.CurrentNodeVo;
import com.feityz.system.vo.RollBackInput;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class ProcessIncetanceServiceImpl implements IProcessIncetanceService {

    @Autowired
    private ProcessService processService;
    @Autowired
    private ProcessIncetanceMapper processIncetanceMapper;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private IUserService userService;
    @Override
    public IPage<ProcessIncetanceVo> pageByAssignee(ProcessIncetanceVo condition, Page<ProcessIncetanceVo> page) {
        page.setRecords(processIncetanceMapper.pageByAssignee(page,condition));
        return page;
    }

    @Override
    public IPage<ProcessIncetanceVo> pageByPromoter(ProcessIncetanceInput condition, Page<ProcessIncetanceVo> page) {
        page.setRecords(processIncetanceMapper.pageByPromoter(page,condition));
        return page;
    }

    @Override
    public IPage<ProcessIncetanceVo> pageAll(ProcessIncetanceVo condition, Page<ProcessIncetanceVo> page) {
        page.setRecords(processIncetanceMapper.pageAll(page,condition));
        return page;
    }

    @Override
    public IPage<ProcessIncetanceVo> pageByPromoterHis(ProcessIncetanceHisInput condition, Page<ProcessIncetanceVo> page) {
        page.setRecords(processIncetanceMapper.pageByPromoterHis(page,condition));
        return page;
    }

    @Override
    public void deleteHisInstance(Long instanceId) {
        processIncetanceMapper.deleteHisInstance(instanceId);
    }

    @Override
    public Map getInstanceParms(long instanceId){

        ProcessInstance instance = processService.getProcessInstanceById(instanceId);

        String url = "";
        String bizId = "";

        if(instance != null){
            ProcessDefinition definition = processService.getProcessById(instance.getProcessId());

            Node node = definition.getNode(instance.getCurrentNode());

            url = definition.getStartProcessUrl();

            if(node instanceof TaskNode){
                TaskNode taskNode = (TaskNode) node;
                if(StringUtils.isNotEmpty(taskNode.getUrl())){
                    url = taskNode.getUrl();
                }
            }
            bizId = instance.getBusinessId();
        }else{
            HistoryProcessInstance historyProcessInstance = historyService.getHistoryProcessInstance(instanceId);
            //当前实例如果查不到,那表示该实例已经结束
            ProcessDefinition definition = processService.getProcessById(historyProcessInstance.getProcessId());

            url = definition.getStartProcessUrl();
            bizId = historyProcessInstance.getBusinessId();
        }

        Map result = new HashMap();
        result.put("url",url);
        result.put("bizId",bizId);
        return result;

    }

    @Override
    public List<CurrentNodeVo> getCurrent(Long instanceId){
        List<CurrentNodeVo> nodes = new ArrayList<>();

        List<ProcessInstance> instances = new ArrayList<>();

        ProcessInstance processInstanceById = processService.getProcessInstanceById(instanceId);

        List child = processService.createProcessInstanceQuery().parentId(instanceId).list();

        if(child.size()>0){

            instances = processService.createProcessInstanceQuery().parentId(instanceId).list();

        }else{
            if(processInstanceById.getParentId()!=0){
                instances.add(processService.getProcessInstanceById(processInstanceById.getParentId()));
            }else {
                instances.add(processService.getProcessInstanceById(instanceId));
            }

        }

        for (ProcessInstance instance : instances) {
            List<Task> tasks = taskService.createTaskQuery()
                    .processInstanceId(instance.getId())
                    .addTaskState(TaskState.Created)
                    .addTaskState(TaskState.Ready)
                    .addTaskState(TaskState.InProgress)
                    .list();
            //查出来可能会有多个Task
            for (Task task: tasks) {
                TaskNode taskNode = (TaskNode) processService.getProcessById(instance.getProcessId()).getNode(task.getNodeName());
                //任务对应的节点信息
                List<UserData> userData = taskNode.getUserData();
                CurrentNodeVo node = new CurrentNodeVo();
                node.setNodeName(task.getNodeName());
                node.setUserData(userData);
                node.setUrl(task.getUrl());
                node.setTaksId(task.getId());
                String userIds = task.getOwner();
                if(StringUtils.isNotEmpty(userIds)){
                    List users =userService.lambdaQuery().in(User::getId,userIds.split(",")).list();
                    node.setAssignee(users);
                }
                nodes.add(node);
            }
        }

        return nodes;
    }


    @Override
    @Transactional
    public void endProcessInstance(RollBackInput input){
        taskService.rollback(input.getTaskId(),"结束",null,new TaskOpinion(input.getOpinion(),input.getOperation()));
    }
}
